package com.example.demo.controller;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.FiFinance;
import com.example.demo.entity.SysUser;
import com.example.demo.exception.CustomException;
import com.example.demo.mapper.FinanceMapper;
import com.example.demo.service.FinanceService;
import com.example.demo.utils.TokenUtils;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.*;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.*;

@RestController
@RequestMapping("/finance")
public class FinanceController extends BaseController{

    @Resource
    FinanceMapper financeMapper;

    @Autowired
    FinanceService financeService;

    @PostMapping
    public Result<?> save(@RequestBody FiFinance fiFinance,HttpServletRequest request) {
        fiFinance.setCreateTime(new Date());
        financeMapper.insert(fiFinance);
        return Result.success();
    }

    @PutMapping
    public Result<?> update(@RequestBody FiFinance fiFinance,HttpServletRequest request) {
        SysUser user = TokenUtils.getUserInfo(request);
        if (user == null)
            return Result.error("500", "未获取到user信息");
        fiFinance.setUpdateUser(user.getUsername());
        fiFinance.setUpdateTime(new Date());
        financeMapper.updateById(fiFinance);
        return Result.success();
    }

    @Transactional
    @DeleteMapping("/{ids}")
    public Result<?> delete(@PathVariable @NotBlank String ids, HttpServletRequest request) {
        SysUser user = TokenUtils.getUserInfo(request);
        if (user == null)
            return Result.error("500", "未获取到user信息");
        List<String> idList = Arrays.asList(ids.split(","));
        for (String ID : idList) {
            FiFinance fiFinanceInfo = financeMapper.selectById(ID);
            Optional.ofNullable(fiFinanceInfo).orElseThrow(() ->  new CustomException("500001","该数据不存在"));
            fiFinanceInfo.setUpdateUser(user.getUsername());
            fiFinanceInfo.setUpdateTime(new Date());
            financeMapper.updateById(fiFinanceInfo);
            financeMapper.deleteById(fiFinanceInfo.getId());
        }
        return Result.success("删除成功");
    }

//    @DeleteMapping("/{id}")
//    public Result<?> delete(@PathVariable Integer id) {
//        financeMapper.deleteById(id);
//        return Result.success();
//    }


    @GetMapping("/{id}")
    public Result<?> getById(@PathVariable Integer id) {
        return Result.success(financeMapper.selectById(id));
    }

/**
 * 
 * @author fqc
 * @date 2023/12/7 16:19
 * @param pageNum 页码
 * @param pageSize 数量
 * @param project 项目名称
 * @param merchant 商户名称
 * @param startTime 开始时间
 * @param endTime  结束时间
 * @return com.example.demo.common.Result<?>
 */
    @GetMapping
    public Result<?> findPage(@RequestParam(defaultValue = "1") Integer pageNum,
                              @RequestParam(defaultValue = "10") Integer pageSize,
                              @RequestParam(defaultValue = "") String project,
                              @RequestParam(defaultValue = "") String merchant,
                              @RequestParam(defaultValue = "") String startTime,
                              @RequestParam(defaultValue = "") String endTime) {
        LambdaQueryWrapper<FiFinance> wrapper = Wrappers.<FiFinance>lambdaQuery();
        if (StrUtil.isNotBlank(project)) {
            wrapper.like(FiFinance::getProject, project);
        }
        if (StrUtil.isNotBlank(merchant)) {
            wrapper.like(FiFinance::getMerchant, merchant);
        }
        if(StrUtil.isNotBlank(startTime )|| StrUtil.isNotBlank(endTime)){
            wrapper.and(q -> {
                if(StrUtil.isNotBlank(startTime)) {
                    q.ge(FiFinance::getPayTime, startTime);
                }
                if(StrUtil.isNotBlank(endTime)){
                    q.le(FiFinance::getPayTime,endTime);
                }
            });
        }
        Page<FiFinance> financePage = financeMapper.selectPage(new Page<>(pageNum, pageSize), wrapper);
        return Result.success(financePage);
    }

    /**
     *
     * @author fqc
     * @date 2023/11/21 16:51
     * @param checkDeptIds 导出的ids
     * @param response 响应
     */
    @ApiOperation(value = "导出excel表格", notes = "导出明细excel表格")
    @GetMapping("/export/{checkDeptIds}")
    public void exportInfo(@PathVariable("checkDeptIds") String checkDeptIds, HttpServletResponse response) {

        Map<Integer, List<Map<String, Object>>> maps=financeService.getMaps(checkDeptIds);

        try {
            TemplateExportParams params = new TemplateExportParams("static/financeTemplate.xlsx",true);
            Workbook workbook = ExcelExportUtil.exportExcelClone(maps,params);//<!-- POI的版本要对应，不然依赖冲突，找不到方法什么的都是版本问题，版本一致的，可以忽略-->
            // 设置文件名
            String uuidFileName=UUID.randomUUID().toString().replace("-","");
            response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(Instant.now().toEpochMilli()+".xlsx", "UTF-8"));
            response.setContentType("application/vnd.ms-excel;charset=gb2312");

            workbook.write(response.getOutputStream());
            workbook.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 
     * @author fqc
     * @date 2023/11/21 16:51
     * @param file 
     * @return com.example.demo.common.Result<?>
     */
    @Transactional
    @PostMapping("/import")
    public Result<?> imp(MultipartFile file,HttpServletRequest request) {
        List<FiFinance> fiFinances = CollUtil.newArrayList();
        SysUser user = TokenUtils.getUserInfo(request);
        if (user == null)
            return Result.error("500", "未获取到user信息");
        try {
            InputStream inputStream = file.getInputStream();
            ExcelReader reader = ExcelUtil.getReader(inputStream);
            List<List<Object>> list = reader.read(1);
            for (List<Object> row : list) {
                FiFinance finance = new FiFinance();
                finance.setMerchant(row.get(1).toString());
                finance.setProject(row.get(2).toString());
                finance.setStartTime(row.get(3).toString().substring(0,10));
                finance.setEndTime(row.get(4).toString().substring(0,10));
                finance.setPayTime(row.get(5).toString().substring(0,10));
                finance.setAmountReceivable(new BigDecimal(row.get(6).toString()));
                if (row.get(7) == null || row.get(7).toString().equals("H")){
                    finance.setAmountReceived(BigDecimal.ZERO);
                }else{
                    finance.setAmountReceived(new BigDecimal(row.get(7).toString()));
                }
                finance.setOutstandingAmount(new BigDecimal(row.get(8).toString()));
                finance.setCreateUser(user.getUsername());
                finance.setCreateTime(new Date());
                fiFinances.add(finance);
            }
        }catch (Exception e){
            return Result.error("500","导入excel失败");
        }

        if(financeService.saveBatch(fiFinances)){
            return Result.success();
        }else{
            return Result.error("5001","导入失败");
        }
    }

}
